﻿


using BJYJ_Admin.Core.Utils.ResultUtils;
using Org.BouncyCastle.Asn1.X509;

namespace BJYJ_Admin.Application.System.Services.User
{
    [ApiDescriptionSettings("System")]
    public class SysUserService : IDynamicApiController, ITransient
    {

        public readonly ISqlSugarClient _db;
        private readonly IMemoryCache _memoryCache;
        public readonly SysRoleService _sysRoleService;
        public SysUserService(ISqlSugarClient db, IMemoryCache memoryCache, SysRoleService sysRoleService)
        {
            _db = db;
            _memoryCache = memoryCache;
            _sysRoleService = sysRoleService;
        }
        /// <summary>
        /// 获取用户列表信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("获取用户列表信息")]
        public virtual async Task<PageResult<UserOutDto>> GetUserList([FromQuery] UserInfoInput input)
        {
            RefAsync<int> totalCount = 0;
            var user = await _db.Queryable<SYS_USERS>().
                        WhereIF(!string.IsNullOrWhiteSpace(input.USERNAME), x => x.USERNAME.Contains(input.USERNAME))
                        .WhereIF(!string.IsNullOrWhiteSpace(input.TRUENAME), x => x.TRUENAME.Contains(input.TRUENAME))
                        .WhereIF(!string.IsNullOrWhiteSpace(input.AREANUMBER), x => x.AREANUMBER.Contains(input.AREANUMBER))
                        .WhereIF(!string.IsNullOrWhiteSpace(input.PHONE), x => x.PHONE.Contains(input.PHONE))
                        .WhereIF(input.ISENABLED.HasValue, x => x.ISENABLED == input.ISENABLED)
                        .OrderBy(x => x.ID, OrderByType.Desc)
                        .Select(user => new UserOutDto
                        {
                            ID = user.ID,
                            USERNAME = user.USERNAME,
                            TRUENAME = user.TRUENAME,
                            PHONE = user.PHONE,
                            EMAILE = user.EMAILE,
                            JGJB = user.JGJB,
                            AREANUMBER = user.AREANUMBER,
                            USER_TYPE = user.USER_TYPE,
                            DEPTID = user.DEPTID,
                            FKID = user.FKID,
                            IMGURL = user.IMGURL,
                            LASTLOGINDATE = user.LASTLOGINDATE,
                            ISENABLED = user.ISENABLED

                        })
                        .ToPageListAsync(input.page, input.limit, totalCount);
            return new PageResult<UserOutDto>
            {
                page = input.page,
                limit = input.limit,
                totalcount = totalCount,
                data = user
            };
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("添加用户")]
        public virtual async Task AddUser(AddUserInput input)
        {
            var haveInfo = _db.Queryable<SYS_USERS>().Where(x => x.USERNAME == input.USERNAME).FirstAsync();
            if (haveInfo.Result != null)
            {
                throw Oops.Oh(ErrorCodeEnum.U0005);
            }
            var user = new SYS_USERS
            {
                USERNAME = input.USERNAME,
                TRUENAME = input.TRUENAME,
                PASSWD = MD5Encryption.Encrypt(input.USERNAME + App.Configuration["PassWD:PassWD"]),
                PHONE = input.PHONE,
                EMAILE = input.EMAILE,
                JGJB = input.JGJB,
                AREANUMBER = input.AREANUMBER,
                USER_TYPE = input.USER_TYPE,
                DEPTID = input.DEPTID,
                ISENABLED = input.ISENABLED,
                CREATE_TIME = DateTime.Now,
                CREATE_BY = App.User?.FindFirstValue("ID")
            };
            var id = _db.Insertable(user).ExecuteReturnIdentity();
            if (id > 0)
            {
                var UserRoleInfo = new UserPowerDto
                {
                    USERID = id,
                    ROLES = input.roleids
                };
                await _sysRoleService.SavePowerForUserByID(UserRoleInfo);
            }
            else
            {
                throw Oops.Oh(ErrorCodeEnum.OP0001);
            }
        }
        /// <summary>
        /// 获取指定ID用户信息，用于用户管理的编辑
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [DisplayName("获取指定ID用户信息，用于用户管理的编辑")]
        public virtual async Task<UserOutDto> GetUserInfoByID(int id)
        {
            var user = await _db.Queryable<SYS_USERS>().
                      Select(user => new UserOutDto
                      {
                          ID = user.ID,
                          USERNAME = user.USERNAME,
                          TRUENAME = user.TRUENAME,
                          PHONE = user.PHONE,
                          EMAILE = user.EMAILE,
                          JGJB = user.JGJB,
                          AREANUMBER = user.AREANUMBER,
                          USER_TYPE = user.USER_TYPE,
                          DEPTID = user.DEPTID,
                          FKID = user.FKID,
                          IMGURL = user.IMGURL,
                          LASTLOGINDATE = user.LASTLOGINDATE,
                          ISENABLED = user.ISENABLED,
                          ROLEIDS = SqlFunc.Subqueryable<SYS_USER_ROLE>().Where(z => z.UID == user.ID).SelectStringJoin(z => z.RID.ToString(), ",")
                      }).Where(x => x.ID == id).FirstAsync();
            return user;
        }
        /// <summary>
        /// 获取指定ID用户信息，用于用户编辑个人信息
        /// </summary>
        /// <returns></returns>
        [DisplayName("获取指定ID用户信息，用于用户编辑个人信息")]
        public virtual async Task<UserOutDto> GetUserInfoForEdit()
        {
            var id = int.Parse(App.User?.FindFirstValue("ID"));
            var user = await _db.Queryable<SYS_USERS>().
                      Select(user => new UserOutDto
                      {
                          ID = user.ID,
                          USERNAME = user.USERNAME,
                          TRUENAME = user.TRUENAME,
                          PHONE = user.PHONE,
                          EMAILE = user.EMAILE,
                          DEPTNAME = SqlFunc.Subqueryable<SYS_DEPT>().Where(z => z.ID == user.DEPTID).Select(z => z.NAME),
                          JGJB = user.JGJB,
                          USER_TYPE = user.USER_TYPE
                      }).Where(x => x.ID == id).FirstAsync();
            return user;
        }
        /// <summary>
        /// 更新用户信息，用于个人信息自己信息，只更新了名字、电话、邮箱
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("更新用户信息，用于个人信息自己信息，只更新了名字、电话、邮箱")]
        public virtual async Task UpdateUserForEdit(UpdateUserInput input)
        {
            var id = int.Parse(App.User?.FindFirstValue("id"));
            var result = await _db.Updateable<SYS_USERS>()
                                    .SetColumns(it => it.TRUENAME == input.TRUENAME)
                                    .SetColumns(it => it.PHONE == input.PHONE)
                                    .SetColumns(it => it.EMAILE == input.EMAILE)
                                    .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                                    .SetColumns(it => it.UPDATE_BY == id.ToString())
                                    .Where(it => it.ID == id)
                                    .ExecuteCommandAsync();
            if (result == 0)
                throw Oops.Oh(ErrorCodeEnum.OP0000);
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("更新用户信息")]
        public virtual async Task UpdateUser(UpdateUserInput input)
        {
            input.UPDATE_TIME = DateTime.Now;
            input.UPDATE_BY = App.User?.FindFirstValue("ID");
            var result = await _db.Updateable<SYS_USERS>(input)
                   .IgnoreColumns(u => new { u.USERNAME, u.ISENABLED })
                   .ExecuteCommandAsync();
            if (result == 0)
                throw Oops.Oh(ErrorCodeEnum.OP0002);
            else
            {
                var roleidList = _db.Queryable<SYS_USER_ROLE>()
                             .Where(x => x.UID == input.ID)
                             .Select(x => x.RID).ToList();
                var roleids = string.Join(",", roleidList.Select(r => r.ToString()));
                if (roleids != input.ROLEIDS)
                {
                    var UserRoleInfo = new UserPowerDto
                    {
                        USERID = input.ID,
                        ROLES = input.ROLEIDS
                    };
                    await _sysRoleService.SavePowerForUserByID(UserRoleInfo);
                }
            }
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("删除用户")]
        public virtual async Task DeleteUser([FromQuery] UserIDDto input)
        {

            // 开启事务处理
            var result = await _db.Ado.UseTranAsync(async () =>
            {
                //1.删除用户
                await _db.Deleteable<SYS_USERS>().Where(x => x.ID == input.ID).ExecuteCommandAsync();
                //2.删除用户角色关联
                await _db.Deleteable<SYS_USER_ROLE>().Where(x => x.UID == input.ID).ExecuteCommandAsync();
            });
            if (!result.IsSuccess)
                throw Oops.Oh(result.ErrorMessage);
        }

        /// <summary>
        /// 重置密码    
        /// </summary>        
        /// <returns></returns>
        [DisplayName("重置密码")]
        public virtual async Task ResetPwd(UserIDDto input)
        {
            var id = App.User?.FindFirstValue("ID");
            var UserName = App.User?.FindFirstValue("USERNAME");
            var user = await _db.Queryable<SYS_USERS>().Where(x => x.ID == input.ID).FirstAsync();
            if (user == null)
            {
                throw Oops.Oh(ErrorCodeEnum.U0002);
            }
            else
            {
                var NewPassWD = MD5Encryption.Encrypt(user.USERNAME + App.Configuration["PassWD:PassWD"]);
                // 清空密码错误次数
                var keyErrorPasswordCount = $"sys_password_error_times:{user.USERNAME}";
                _memoryCache.Remove(keyErrorPasswordCount);
                var result = _db.Updateable<SYS_USERS>()
                           .SetColumns(it => it.PASSWD == NewPassWD)
                           .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                           .SetColumns(it => it.UPDATE_BY == id)
                           .Where(it => it.ID == input.ID)
                           .ExecuteCommand();
                if (result == 0)
                    throw Oops.Oh(ErrorCodeEnum.OP0004);

            }
        }

        /// <summary>
        /// 修改密码    
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("修改密码")]
        public virtual async Task UpdatePwd(ResetPwdUserInput input)
        {
            var ID = int.Parse(App.User?.FindFirstValue("ID"));
            var UserName = App.User?.FindFirstValue("USERNAME");
            var user = await _db.Queryable<SYS_USERS>().Where(x => x.ID == ID).FirstAsync();
            if (user == null)
            {
                throw Oops.Oh(ErrorCodeEnum.U0002);
            }
            else
            {
                var oldPassWD = MD5Encryption.Encrypt(UserName + SM4Encrypt.Decrypt_ECB(input.OLD_PASSWD));
                if (oldPassWD == user.PASSWD)
                {
                    var NewPassWD = MD5Encryption.Encrypt(user.USERNAME + SM4Encrypt.Decrypt_ECB(input.NEW_PASSWD));
                    // 清空密码错误次数
                    var keyErrorPasswordCount = $"sys_password_error_times:{user.USERNAME}";
                    _memoryCache.Remove(keyErrorPasswordCount);
                    var result = _db.Updateable<SYS_USERS>()
                               .SetColumns(it => it.PASSWD == NewPassWD)
                               .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                               .SetColumns(it => it.UPDATE_BY == ID.ToString())
                               .Where(it => it.ID == ID)
                               .ExecuteCommand();
                    if (result == 0)
                        throw Oops.Oh(ErrorCodeEnum.OP0002);
                }
                else
                {
                    throw Oops.Oh(ErrorCodeEnum.U0006);
                }
            }
        }

        /// <summary>
        /// 解除登录锁定
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("解除登录锁定")]
        public virtual async Task UnlockLogin(UserIDDto input)
        {
            var user = await _db.Queryable<SYS_USERS>().Where(x => x.ID == input.ID).FirstAsync();
            if (user == null)
            {
                throw Oops.Oh(ErrorCodeEnum.U0002);
            }
            else
            {
                // 清空密码错误次数
                var keyPasswordErrorTimes = $"sys_password_error_times:{user.USERNAME}";
                _memoryCache.Remove(keyPasswordErrorTimes);
            }
        }
        /// <summary>
        /// 启用禁用用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [DisplayName("启用禁用用户")]
        public virtual async Task UnIsEnable(UnIsEnabledLogin input)
        {
            var id = App.User?.FindFirstValue("ID");
            var user = await _db.Queryable<SYS_USERS>().Where(x => x.ID == input.ID).FirstAsync();
            var UserName = App.User?.FindFirstValue("USERNAME");
            if (user == null)
            {
                throw Oops.Oh(ErrorCodeEnum.U0002);
            }
            else
            {
                // 清空密码错误次数
                var keyErrorPasswordCount = $"sys_password_error_times:{user.USERNAME}";
                _memoryCache.Remove(keyErrorPasswordCount);

                var result = _db.Updateable<SYS_USERS>()
                               .SetColumns(it => it.ISENABLED == input.ISENABLED)
                               .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                               .SetColumns(it => it.UPDATE_BY == id.ToString())
                               .Where(it => it.ID == input.ID)
                               .ExecuteCommand();
                if (result == 0)
                    throw Oops.Oh(ErrorCodeEnum.OP0000);
            }
        }
        /// <summary>
        /// 获取当前用户的指定的父级菜单信息
        /// </summary>
        /// <returns></returns>
        [DisplayName("获取当前用户的指定的父级菜单信息")]
        public virtual async Task<List<SYS_MENU>> GetUserMenuByID(int id)
        {
            RefAsync<int> totalCount = 0;
            var userID = int.Parse(App.User?.FindFirstValue("ID"));
            //left join方式
            //var list = await _db.Queryable<SYS_MENU>()
            //            .LeftJoin<SYS_ROLE_MENU>((menu, role_menu) => menu.ID == role_menu.MID)
            //            .LeftJoin<SYS_USER_ROLE>((menu, role_menu, user_role) =>  role_menu.RID == user_role.RID)
            //            .Where((menu, role_menu, user_role) => user_role.UID == userID && menu.STATUS == 0)
            //            .Distinct()
            //            .OrderBy(menu => menu.PID, OrderByType.Asc)
            //            .OrderBy(menu => menu.ORDER_NUM, OrderByType.Asc)
            //            .ToPageListAsync(0, 1000, totalCount);
            //inner join方式
            return await _db.Queryable<SYS_MENU, SYS_ROLE_MENU, SYS_USER_ROLE>((m, r, u) =>
                           m.ID == r.MID && r.RID == u.RID)
                           .Where((m, r, u) => u.UID == userID && m.STATUS == 0 && m.PARENT_PATH.StartsWith("0," + id.ToString() + ""))
                          .Distinct()
                          .OrderBy(m => m.PID, OrderByType.Asc)
                          .OrderBy(m => m.ORDER_NUM, OrderByType.Asc)
                          .Select((m, r, u) => new SYS_MENU
                          {
                              ID = m.ID,
                              ICON = m.ICON,
                              MENUNAME = m.MENUNAME,
                              MENULINK = m.MENULINK,
                              PID = m.PID,
                              ORDER_NUM = m.ORDER_NUM,
                              DEPTH = m.DEPTH
                          })
                          .ToListAsync();
        }

        /// <summary>
        /// 获取当前用户信息    
        /// </summary>
        /// <returns></returns>
        [DisplayName("获取当前用户信息")]
        public virtual async Task<UserOutDto> GetUserInfo()
        {
            var ID = int.Parse(App.User?.FindFirstValue("ID"));

            return await _db.Queryable<SYS_USERS>().Where(x => x.ID == ID).Select(user => new UserOutDto
            {
                ID = user.ID,
                USERNAME = user.USERNAME,
                TRUENAME = user.TRUENAME,
                PHONE = user.PHONE,
                EMAILE = user.EMAILE,
                JGJB = user.JGJB,
                AREANUMBER = user.AREANUMBER,
                USER_TYPE = user.USER_TYPE,
                DEPTID = user.DEPTID,
                FKID = user.FKID,
                IMGURL = user.IMGURL,
                LASTLOGINDATE = user.LASTLOGINDATE,
                ISENABLED = user.ISENABLED

            }).FirstAsync();

        }
        /// <summary>
        /// 获取配置的平台信息    
        /// </summary>
        /// <returns></returns>
        [DisplayName("获取配置的平台信息")]
        public virtual List<ItemConfig> GetPlatformItem()
        {
            var Item = App.GetConfig<PlatformItemConfig>("PlatFormItem");
            var Items = Item?.Items ?? new List<ItemConfig>();
            return Items;
        }

    }

}
